package facadeOCL;

import java.io.PushbackReader;
import java.io.StringReader;
import java.util.Iterator;
import java.util.List;

import org.netbeans.api.mdr.MDRManager;
import org.netbeans.api.mdr.MDRepository;

import converterOCL.ConverterOCL;

import parser.astgen.Heritage;
import parser.astgen.LAttrGMCAstGenerator;
import parser.sablecc.lexer.Lexer;
import parser.sablecc.node.Start;
import parser.sablecc.parser.Parser;
import parser.sablecc.parser.ParserException;
import project.Project;
import uml2.kernel.Constraint;
import facade.UserFacade;

public class ParserFacade {

		public void addOclExpression(String ocl, Project p) throws Exception {
			MDRepository repository = null;
			boolean rollbackneeded = false;
			String error_message = "";
			StackTraceElement [] ste = null;
			
			Lexer lexer = new Lexer (new PushbackReader(new StringReader(ocl),1024));
			Parser parser = new Parser(lexer);
			try {
				// Begin Transaction
				repository = MDRManager.getDefault().getDefaultRepository();
				repository.beginTrans(true);
				  
				// Parse OCL2.0 constraints (syntax)	  
				Start ast = parser.parse();
			
				long start_time = System.currentTimeMillis();
				// Semantics       
				// We use a Visitor Pattern
				ast.apply(new LAttrGMCAstGenerator(p), new Heritage());
	        
				long stop_time = System.currentTimeMillis();
				System.out.println("Compilation time: " + (stop_time - start_time) + " ms\n");       
			} 
			catch (ParserException pe) {
				System.out.println("Parse error at "+pe.getToken().getText()+" : "+pe.getMessage());
				rollbackneeded = true;
			} 
			catch (Exception e) {
				if (e.getMessage()!=null) {
					error_message = "Incorrect Expression\nProblem: "+e.getMessage()+"";
				}
				else {
					e.printStackTrace();
					error_message = "\nInternal Error. Report stack trace to avillegas@lsi.upc.edu";
					ste = e.getStackTrace();
				}
				rollbackneeded = true;
			}
			finally {
				// Close the transaction
				// If rollback is needed, it drops the new changes
				repository.endTrans(rollbackneeded);
				if (rollbackneeded) {
					Exception e = new Exception("\n"+error_message);
					if (ste != null) e.setStackTrace(ste);
					throw e;
				}
			}
		}
		
		public boolean deleteOclExpression(String name, Project p) {
			UserFacade uf = new UserFacade(p);
			Constraint c = uf.findConstraintByName(name);
			if (c == null) return false;
			else {
				System.out.println(c.getName());
				DeleteVisitor dv = new DeleteVisitor(p);
				return dv.remove(c);
			}
		}
		
		public List getAllOclExpressions(String xmiOrigen) {
			return null;
		}
		
		public void importOcl(List aoe, String xmiDesti) throws Exception {
			Project p = new Project("project_auxiliar");
			p.importXMI(xmiDesti);
			Iterator it = aoe.iterator();
			while (it.hasNext()) {
				String ocl_expression = (String) it.next();
				addOclExpression(ocl_expression, p);
			}
			p.saveXMI(xmiDesti);
			p.closeProject();
		}
		
		public String getStringOclExpression(String name, Project p){
			UserFacade uf = new UserFacade(p);
			Constraint c = uf.findConstraintByName(name);
			ConverterOCL cocl = new ConverterOCL(p);
			return cocl.convert(c);
		}
		
		public String getStringOclExpression(Constraint c, Project p) {
			ConverterOCL cocl = new ConverterOCL(p);
			return cocl.convert(c);
		}
				
}
